package handlers

import (
	"restaurant-system/config"
	"restaurant-system/internal/models"
	"time"

	"github.com/gin-gonic/gin"
)

// 创建桌位请求
type CreateTableRequest struct {
	Number      string `json:"number" binding:"required"`
	Capacity    int    `json:"capacity" binding:"required,min=1"`
	Location    string `json:"location" binding:"required"`
	Description string `json:"description"`
	Status      string `json:"status"`
}

// 创建桌位
func CreateTable(c *gin.Context) {
	var req CreateTableRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	if req.Status == "" {
		req.Status = "free"
	}

	table := models.Table{
		Number:      req.Number,
		Capacity:    req.Capacity,
		Location:    req.Location,
		Status:      req.Status,
		Description: req.Description,
	}

	if err := config.DB.Create(&table).Error; err != nil {
		c.JSON(500, gin.H{"error": "创建桌位失败"})
		return
	}

	c.JSON(200, gin.H{"message": "创建桌位成功", "table": table})
}

// 更新桌位请求
type UpdateTableRequest struct {
	Capacity    int    `json:"capacity" binding:"required,min=1"`
	Location    string `json:"location" binding:"required"`
	Description string `json:"description"`
	Status      string `json:"status"`
}

// 更新桌位
func UpdateTable(c *gin.Context) {
	id := c.Param("id")
	var req UpdateTableRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	var table models.Table
	if err := config.DB.First(&table, id).Error; err != nil {
		c.JSON(404, gin.H{"error": "桌位不存在"})
		return
	}

	table.Capacity = req.Capacity
	table.Location = req.Location
	table.Description = req.Description
	if req.Status != "" {
		table.Status = req.Status
	}

	if err := config.DB.Save(&table).Error; err != nil {
		c.JSON(500, gin.H{"error": "更新桌位失败"})
		return
	}

	c.JSON(200, gin.H{"message": "更新桌位成功", "table": table})
}

// 删除桌位
func DeleteTable(c *gin.Context) {
	id := c.Param("id")

	var table models.Table
	if err := config.DB.First(&table, id).Error; err != nil {
		c.JSON(404, gin.H{"error": "桌位不存在"})
		return
	}

	if table.Status != "free" {
		c.JSON(400, gin.H{"error": "桌位正在使用中，无法删除"})
		return
	}

	if err := config.DB.Unscoped().Delete(&table).Error; err != nil {
		c.JSON(500, gin.H{"error": "删除桌位失败"})
		return
	}

	c.JSON(200, gin.H{"message": "删除桌位成功"})
}

// 获取桌位列表
func GetTables(c *gin.Context) {
	var tables []models.Table
	if err := config.DB.Find(&tables).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取桌位列表失败"})
		return
	}

	c.JSON(200, gin.H{"tables": tables})
}

// 预订桌位请求
type ReserveTableRequest struct {
	TableID     uint      `json:"table_id" binding:"required"`
	StartTime   time.Time `json:"start_time" binding:"required"`
	EndTime     time.Time `json:"end_time" binding:"required,gtfield=StartTime"`
	GuestCount  int       `json:"guest_count" binding:"required,min=1"`
	PhoneNumber string    `json:"phone_number" binding:"required"`
	Notes       string    `json:"notes"`
}

// 预订桌位
func ReserveTable(c *gin.Context) {
	userID, _ := c.Get("userID")
	var req ReserveTableRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	// 检查桌位是否存在
	var table models.Table
	if err := config.DB.First(&table, req.TableID).Error; err != nil {
		c.JSON(404, gin.H{"error": "桌位不存在"})
		return
	}

	// 检查桌位容量是否足够
	if table.Capacity < req.GuestCount {
		c.JSON(400, gin.H{"error": "桌位容量不足"})
		return
	}

	// 检查时间段是否可用
	var conflictCount int64
	config.DB.Model(&models.TableReservation{}).
		Where("table_id = ? AND status = 'confirmed' AND NOT (end_time <= ? OR start_time >= ?)",
			req.TableID, req.StartTime, req.EndTime).
		Count(&conflictCount)

	if conflictCount > 0 {
		c.JSON(400, gin.H{"error": "该时间段已被预订"})
		return
	}

	// 创建预订
	reservation := models.TableReservation{
		UserID:      userID.(uint),
		TableID:     req.TableID,
		StartTime:   req.StartTime,
		EndTime:     req.EndTime,
		GuestCount:  req.GuestCount,
		Status:      "pending",
		PhoneNumber: req.PhoneNumber,
		Notes:       req.Notes,
	}

	if err := config.DB.Create(&reservation).Error; err != nil {
		c.JSON(500, gin.H{"error": "创建预订失败"})
		return
	}

	c.JSON(200, gin.H{"message": "预订成功，等待确认", "reservation": reservation})
}

// 更新预订状态请求
type UpdateReservationStatusRequest struct {
	Status string `json:"status" binding:"required,oneof=confirmed cancelled completed"`
}

// 更新预订状态
func UpdateReservationStatus(c *gin.Context) {
	id := c.Param("id")
	var req UpdateReservationStatusRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	var reservation models.TableReservation
	if err := config.DB.First(&reservation, id).Error; err != nil {
		c.JSON(404, gin.H{"error": "预订不存在"})
		return
	}

	// 开启事务
	tx := config.DB.Begin()

	// 更新预订状态
	if err := tx.Model(&reservation).Update("status", req.Status).Error; err != nil {
		tx.Rollback()
		c.JSON(500, gin.H{"error": "更新预订状态失败"})
		return
	}

	// 更新桌位状态
	var tableStatus string
	switch req.Status {
	case "confirmed":
		tableStatus = "reserved"
	case "cancelled", "completed":
		tableStatus = "free"
	default:
		tableStatus = "free"
	}

	if err := tx.Model(&models.Table{}).Where("id = ?", reservation.TableID).
		Update("status", tableStatus).Error; err != nil {
		tx.Rollback()
		c.JSON(500, gin.H{"error": "更新桌位状态失败"})
		return
	}

	tx.Commit()
	c.JSON(200, gin.H{"message": "更新预订状态成功"})
}

// 获取用户预订列表
func GetUserReservations(c *gin.Context) {
	userID, _ := c.Get("userID")
	var reservations []models.TableReservation

	if err := config.DB.Preload("Table").Where("user_id = ?", userID).
		Order("created_at desc").Find(&reservations).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取预订列表失败"})
		return
	}

	c.JSON(200, gin.H{"reservations": reservations})
}
